That doc will explain you something about Wild's animation engine. To understand everything, it's VERY important that you know perfectly the 3D World rappresention in Wild, so if you have any doubt please re-read the doc (or ask me if something is reaaly obscure...).
The most important object in animation is an Action. This defines a complex movement of an Alien (so also an Arena can be animated, because it is also an Alien... remember ?). An action can be something like "kick", "jump", "open the door", "prepare to shoot", or anything else wich involves the full Alien.
An Action is split into Moves. A Move defines a simple movement (so a rotation + traslation) of a Sector, so a part of an Alien, for example a leg, an arm... A Move has a starting time and a duration, and can do a traslation, a rotation, or both.
Those (Actions and Moves) are fixed structs, so they are valid for any Alien. What I mean is that a "jump" action will contain a list of Moves to move the legs, and a bit more, but will NOT contain the starting time when the single Alien started jumping.
This is handled by the Doing struct. This is allocated every time you call the DoAction(), and will take the current time (or a specified time) as start, and will contain all the temp data, the temp ref, and everything is needed to calc the positions of any SPECIFIC Alien: the Action is the model, the instructions to make someone doing something, the Doing is the data of the single animated object. There is also a substruct, the DoingSector, wich contains the data of the single animated Sector, but is not important for you because is only internally used.
Now some more specific stuff... . We will concentrate on Moves, infact the Action struct contains (nearly) only a list of moves sorted in starting order... . A Move is defined by: 1) a Starting time, relative to the action's starting time, so if you set a starting time of 10 means that this move is executed 10 ticks after the DoAction()'s call time. 2) a Duration, wich means the time needed by this movement to be executed. 3) a CommandList, wich contains an array of commands to set the X,Y,Z,R,RV. That's the most important part; let's see what those X,Y,Z,R,RV are.
The X,Y,Z are the coords of the origin of the Sector's ref (the ref_O), and are relative to the parent (so they are the Rel ones). You can set, for these, the C,V or A: the C means the current value (at the starting time of the move), the V means the speed of changing for this variable, and the A is the acceleration. So, the position of the ref_O at the tick t (relative to the starting of the move (so t=0 at start of move)) is:
O(Ox,Oy,Oz)
Ox = CX+t*VX+t^2*AX/2
Oy = CY+t*VY+t^2*AY/2
Oz = CZ+t*VZ+t^2*AZ/2
The speed vector at the tick t is:
V(Vx,Vy,Vz)
Vx = VX+t*AX
Vy = VY+t*AY
Vz = VZ+t*AZ
Those are simple cynematic rules...
The R is the rotation of the Sector, and it rotates around the RV vector. For R you can set only V,A : the C makes no sense, you can't set a point where R=0: you can only rotate with a certain speed and acceleration. (If anybody thinks different and knows a way to set an absolute R, so can set C, tell-me !). For RV you can only set C, because this is the rotation axis (relative to the parent sector, and passing through the origin (the ref_O)) and is a vector, and it can't move during the move. If you want it moving, you have to make it child of another rotating Sector, but we will see some examples later...
An important thing: the C format is 32.0 bit (long integer), the V and A is 16.16 bit (so you can obtain it by having the correct value ang multiplying it for 65536 (=2^16) : this allow fractional numbers). The tick unit is 1/50 of second. Now, it's done by using a vertical blank interrupt, so it may be variable depending on the screenmode: I'll fix soon by using a cia timer interrupt...
Let's see some code !
static struct WildMoveCommand DropCommands[]={
{MOVECOMMAND_SET,TARGET_Y|TARGET_V,-100000},
{MOVECOMMAND_SET,TARGET_Y|TARGET_A,1200},
{MOVECOMMAND_SET,TARGET_X|TARGET_V,0},
{MOVECOMMAND_SET,TARGET_Z|TARGET_V,0},
{MOVECOMMAND_END,0,0}};
These are the command for the unique move wich defines the Drop action in the Fountain Of Fire demo. As you see, any drop makes a movement starting with a speed to the high (remember that in Wild the Y axis is positive in the low part of the screen) and with an acceleration (that we can call gravity) to the bottom. The speed of X and Z is 0 here, so the movement is vertical. In the demo, these are modified by a Rnd() value. Remember that you can reutilize the WildMoveCommand array, because when using BuildWildObject() a copy is made. Here is the code to make an action:
action=BuildWildObjectTags( WIBU_ObjectType,OBJECT_Action,
WIBU_BuildObject,TRUE,
WIBU_WildApp,SimpleApp,
ATTR_ACTION_SECTORS,1,
ATTR_ACTION_STOPCALL,&KillDropHook,
0,0);
BuildWildObjectTags( WIBU_ObjectType,OBJECT_Move,
WIBU_BuildObject,TRUE,
WIBU_WildApp,SimpleApp,
ATTR_MOVE_SECTORID,1,
ATTR_MOVE_STARTER,0,
ATTR_MOVE_DURATION,200,
ATTR_MOVE_COMMANDLIST,&DropCommands[0],
FRIEND_MOVE_ACTION,action,0,0);
The tags explained: the ATTR_ACTION_SECTOR means the number of sectors involved in the action: for example, if you have to animate a leg, you can have 3 sectors: the topleg, the bottomleg, the foot; here you have just one. The ATTR_ACTION_STOPCALL is a Hook to be called when the action is finished, here is used to kill the Drop sector. The ATTR_MOVE_SECTORID is the ID of the sector this move is referred to: here, there is only one. The IDs are assigned basing in the order you specify the sectors in the DoAction call... see above...
struct WildSector *sects[2]={newdrop,0};
DoActionTags(SimpleApp, WIDA_Alien,SimpleArena,
WIDA_Action,action,
WIDA_Sectors,§s[0],0,0);
That's the call that starts the animation. The tags: WIDA_Alien is the alien wich contains the sectors involved; WIDA_Action is the action to do; WIDA_Sectors is an array containing the sectors involved in the action. The order IS meaningful: if you have the "Jump" action, and you decide in the Moves defining that ID 1 is the topleg, ID 2 is the bottomleg, ID 3 is the foot, you must specify them in this order: topleg,bottomleg,foot.
To complete the whole, remember to call the WildAnimate() in the main cycle...